package com.blog.web;

import java.io.File;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.blog.domain.*;
import org.apache.commons.codec.binary.Base64;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.tuple.Pair;

public final class WebUtils {

	private static final String LOGIN = "_BLOG_LOGIN";
	private static final String SPLIT = "@@##@@"; 
	private static final String PATTERN = "yyyy-MM-dd HH:mm:ss";

	public static String getCookie( HttpServletRequest req, String key ){
		Cookie[] cks = req.getCookies();
		if( cks == null ){
			return null;
		}
		for( Cookie c : cks ){
			if( key.equals(c.getName()) ){
				return c.getValue();
			}
		}
		return null;
	}
	
	public static void setCookie( HttpServletRequest request, HttpServletResponse response, String name, String val ){
		setCookie(response, name, val, getServer(request), 7*24*60*60);
	}

	public static String getServer(HttpServletRequest req){
		return getServer(req.getServerName());
	}

	public static String getServer(String server){
		if( server.matches("\\d+\\.\\d+\\.\\d+\\.\\d+") ){  //IP
			return server;
		}
		return server.replaceFirst("(.*?)\\.",".");
	}

	public static boolean fromAjax( HttpServletRequest request ){
		return request.getHeader("X-Requested-With") != null;
	}
	
	public static void setCookie(HttpServletResponse response, String name, String val, String domain, int expir ){
		Cookie c = new Cookie(name, val);
		c.setDomain(domain);
		c.setMaxAge(expir);
		c.setPath("/");
		response.addCookie(c);
	}
	
	public static String base64( String str ){
		return new String(Base64.encodeBase64(str.getBytes(Charset.forName("UTF-8"))));
	}
	
	public static String encry( String k, String v ){
		return k + SPLIT + base64(v);
	}
	
	public static void addLoginCookie(HttpServletRequest request, HttpServletResponse response, User u ){
		setCookie(request, response, LOGIN, encry(u.getUserName(), u.getUserPwd()));
	}
	
	public static boolean validUser(HttpServletRequest req){
		User u = getUser(req);
		if( u == null ){
			return false;
		}
		User vu = User.getUserByName(u.getUserName());
		if( vu == null ){
			return false;
		}
		return base64(vu.getUserPwd()).equals(u.getUserPwd());
	}
	
	public static User getUser( HttpServletRequest req ){
		String val = getCookie(req, LOGIN);
		if( val != null ){
			String[] pair = val.split(SPLIT);
			if( pair.length == 2){
				String name = pair[0];
				String passwd = pair[1];
				return new User(name, passwd);
			}
		}
		return null;
	}
	
	@SuppressWarnings("unchecked")
	public static <T> Map<String, T> asMap(Object... args) {
		if (args.length % 2 != 0)
			throw new IllegalArgumentException("args.length = " + args.length);

		Map<String, T> map = new HashMap<String, T>();
		for (int i = 0; i < args.length - 1; i += 2)
			map.put(String.valueOf(args[i]), (T) args[i + 1]);
		return map;
	}
	
	public static void needLogin( HttpServletRequest request ){
		if( !validUser(request) ){
			throw new NotLogin("��ҳ����Ҫ��¼���ܷ���!");
		}
	}
	
	@SuppressWarnings("unchecked")
	public static void addData( String type,HttpServletRequest request ,String id){
		if( "fragment".equals(type) ){
			List<? extends POJO> fs = new Fragment().getsByWhere(null);
			request.setAttribute("data", fs);
		}else if( "newTag".equals(type) ){
			List<? extends POJO> tags = new Tag().getsByWhere(null);
			request.setAttribute("data", tags);
		}else if( "archive".equals(type) ){
			List<? extends POJO> archives = new ArticleMeta().getsByWhere(null);
			request.setAttribute("data", archives);
		}else if( "newArticle".equals(type) ){
			if( !"0".equals(id) ){
				//articleMata
				long _id = Long.parseLong(id);
				ArticleMeta meta = (ArticleMeta)(new ArticleMeta().get(_id));
				request.setAttribute("meta", meta);
				
				//article
				Article a = new Article();
				a.setAid(meta.get_id());
				a = (Article)a.get();
				request.setAttribute("article", a);
			}
			//tag
			List<Tag> tags = (List<Tag>)(new Tag().getsByWhere(null));
			request.setAttribute("tags", tags);
		}else if( "upload".equals(type) ){
			Upload u = new Upload();
			List<Upload> uploads = (List<Upload>)(u.getsByWhere(null));
			request.setAttribute("data",uploads);
		}else if( "newFavorites".equals(type) ){
			Favorites fs = new Favorites();
			List<Favorites> all = (List<Favorites>)fs.getsByWhere(null);
			request.setAttribute("data",all);
		}
	}
	
	public static String now(){
		SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
		return sdf.format(new Date());
	}

	public static Pair<String,byte[]> getFile( HttpServletRequest request ) throws FileUploadException {
		String fileName = "";
		byte[] content = new byte[0];
		ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
		List<FileItem> items = upload.parseRequest(request);
		for( FileItem item : items ){
			if( "file".equals(item.getFieldName()) ){
				content = item.get();
			}
			if( "fileName".equals(item.getFieldName()) ){
				fileName = item.getString();
			}
		}
		return Pair.of(fileName,content);
	}

	public static byte[] getMd5(byte[] bytes){
		return DigestUtils.getMd5Digest().digest(bytes);
	}

	public static String getMd5Hex(byte[] bytes){
		return Hex.encodeHexString(getMd5(bytes));
	}

	public static String getUploadDir( HttpServletRequest request ){
		String dir = request.getSession().getServletContext().getRealPath("/upload");
		File file = new File(dir);
		if( !file.exists() ){
			file.mkdirs();
		}
		return dir;
	}

	public static String getUploadPath( HttpServletRequest request ,String fileName){
		return getUploadDir(request) + File.separator + fileName;
	}

	public static String regule(String str){
		return str.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;")
				.replaceAll("\"","&quot;");
	}

}
